#pragma once

#include <memory>
#include <unordered_map>

#include <entt/entt.hpp>

#include "qbe/src/ecs/event.hpp"
#include "qbe/src/ecs/query.hpp"

#include "events.hpp"

namespace qlib {
class Cell;
}

namespace qbe::undoRedoT {
class BaseCommand;
class MacroCommand;

class BaseCommandReceiver;

class UndoRedoModule {
 public:
  UndoRedoModule(entt::registry* _reg, ecs::Query _query, ecs::EventWriter<Event> writer);

  void start(std::shared_ptr<qlib::Cell> cell);
  void end();

  void add(entt::entity e);
  void change(entt::entity e);
  void dele(entt::entity e);

  void add(std::vector<entt::entity> es);
  void change(std::vector<entt::entity> es);
  void dele(std::vector<entt::entity> es);

  void switchCell(std::shared_ptr<qlib::Cell> cell);
  void addCommand(std::shared_ptr<qlib::Cell> cell, BaseCommand* command);

  void resetOldData();

 private:
  std::unordered_map<std::shared_ptr<qlib::Cell>, uint32_t> cellToUndoRedoMap;

  ecs::Query query;
  entt::registry* reg;

  ecs::EventWriter<Event> event_writer;

  bool isStart = false;
  std::shared_ptr<qlib::Cell> cell;

  MacroCommand* macr_command;

  std::vector<entt::entity> add_entitys;
  std::vector<entt::entity> delete_entitys;
  std::vector<entt::entity> change_entitys;

  std::vector<BaseCommandReceiver*> change_receivers;
};

}  // namespace qbe::undoRedoT